﻿
namespace ZDS.Test

open System

open NUnit.Framework
open FsUnit

open ZDS

[<TestFixture>]
type TestLinkList() =
    
    [<Test>]
    member this.TestAppend() =

        let x = new ZLinkList<int>()
        x |> should equal []
        x.Size |> should equal 0
        
        for index = 1 to 3 do
            x.Append <| index*index

        x |> should equal [1;4;9]
        x.Size |> should equal 3

    [<Test>]
    member this.TestGet() =
        let x = new ZLinkList<int>()
        (fun() -> x.[0] |> ignore)
        |> TestUtility.getErrorCode
        |> should equal ErrorCode.OutofRange

        for index = 2 to 5 do
            x.Append <| index*index

        seq {
            for index = 1 to x.Size do
                yield x.[index-1]
        }
        |> should equal [4;9;16;25]

    [<Test>]
    member this.TestSet() =
        let y = new ZLinkList<string>()
        
        (fun() -> y.[0] <- "cheka")
        |> TestUtility.getErrorCode
        |> should equal ErrorCode.OutofRange

        y.Append "cheka"
        y.Append "stasi"

        y.[1] <- "gru"
        y |> should equal ["cheka";"gru"]

    [<Test>]
    member this.TestInsertMiddle() =
        let x = new ZLinkList<int>()

        for index = 1 to 3 do
            x.Append <| index*index

        x.Insert 1 100
        x.Insert 1 200

        x.[1] |> should equal 200
        x |> should equal [1;200;100;4;9]
        x.Size |> should equal 5

        x.Insert (x.Size - 1) 88
        x |> should equal [1;200;100;4;88;9]

    [<Test>]
    member this.TestInsertHead() =
        let x = new ZLinkList<int>()
        
        let original = [100;88;99;66]
        original |> Seq.iter (x.Insert 0)
        
        x |> should equal (original |> List.rev)   
        x.Size |> should equal 4

    [<Test>]
    member this.TestInsertRear() =
        let y = new ZLinkList<int>()

        for index = 1 to 3 do
            y.Insert y.Size index

        y |> should equal [1;2;3]
        y.Size |> should equal 3

        (fun() -> y.Insert (y.Size+1) -1 )
        |> TestUtility.getErrorCode
        |> should equal ErrorCode.OutofRange

        y.Append 9
        y |> should equal [1;2;3;9] // to verify that Rear is correctly set

    [<Test>]
    member this.TestRemoveMiddle() =
        let x = new ZLinkList<int>()

        for index = 1 to 4 do
            x.Append index

        x.Remove 1 |> should equal 2
        x.Remove 1 |> should equal 3
        x.Remove 1 |> should equal 4

        (fun() -> x.Remove 1 |> ignore)
        |> TestUtility.getErrorCode
        |> should equal ErrorCode.OutofRange   

    [<Test>]
    member this.TestRemoveHead() =
        
        let x = new ZLinkList<int>()

        (fun () -> x.Remove 0 |> ignore)
        |> TestUtility.getErrorCode
        |> should equal ErrorCode.OutofRange

        let original = [99;6;88;]
        original |> Seq.iter x.Append

        seq {
            for index = 1 to x.Size do
                yield (x.Remove 0)
        }
        |> should equal original

        x.Size |> should equal 0

    [<Test>]
    member this.TestRemoveRear() =
        let x = new ZLinkList<int>()

        let original = [99;6;88;]
        original |> Seq.iter x.Append

        seq {
            for index = 1 to x.Size do
                yield (x.Remove (x.Size-1))
        }
        |> should equal (original |> List.rev)
        x.Size |> should equal 0

        x.Append 1234
        x |> should equal [1234]

    [<Test>]
    member this.TestShareConcat() =
        let x = new ZLinkList<int>()
        {1..3} |> Seq.iter x.Append

        let y = new ZLinkList<int>()
        y.Append 66
        y.Append 88

        x.ShareConcat y
        x.Size |> should equal 5
        x |> should equal [1;2;3;66;88]

        // !!!!!!!!! the second list is shared
        // !!!!!!!!! so change on one list will reflect on another
        x.Append 100
        x |> should equal [1;2;3;66;88;100]
        y |> should equal [66;88;100]

        y.Remove 1 |> should equal 88
        x |> should equal [1;2;3;66;100]
        
          
        
        

